using System.Data;
using Admin2025.Infrastructure.Data;
using Admin2025.Domain.Repositories;
using Dapper;

namespace Admin2025.Infrastructure.Repositories;

public class Repository<T> : IRepository<T> where T : class
{
  protected readonly IDbConnection _db;
  private readonly string _tableName;

  public Repository(Admin2025DbContext factory)
  {
    _db = factory.CreateConnection();
    _tableName = typeof(T).Name + "s"; // 简单约定表名为实体名 + s
  }

  public async Task<T?> GetByIdAsync(Guid id)
  {
    var sql = $"SELECT * FROM {_tableName} WHERE Id = @Id";
    return await _db.QuerySingleOrDefaultAsync<T>(sql, new { Id = id });
  }

  public async Task<IEnumerable<T>> GetAllAsync()
  {
    var sql = $"SELECT * FROM {_tableName}";
    return await _db.QueryAsync<T>(sql);
  }

  public async Task CreateAsync(T entity)
  {
    var properties = typeof(T).GetProperties()
        .Where(p => p.Name != "Id")
        .Select(p => p.Name);

    var columns = string.Join(", ", properties);
    var values = string.Join(", ", properties.Select(p => "@" + p));

    var sql = $"INSERT INTO {_tableName} ({columns}) VALUES ({values})";
    await _db.ExecuteAsync(sql, entity);
  }

  public async Task UpdateAsync(T entity)
  {
    var properties = typeof(T).GetProperties()
        .Where(p => p.Name != "Id")
        .Select(p => $"{p.Name} = @{p.Name}");

    var setClause = string.Join(", ", properties);

    var sql = $"UPDATE {_tableName} SET {setClause} WHERE Id = @Id";
    await _db.ExecuteAsync(sql, entity);
  }

  public async Task DeleteAsync(Guid id)
  {
    var sql = $"DELETE FROM {_tableName} WHERE Id = @Id";
    await _db.ExecuteAsync(sql, new { Id = id });
  }
}